IM通信系统 (1)

服务端的启动流程

  • 初始化服务端,设置相应参数,配置线程模型,IO模型以及数据连接读写逻辑
  • 实现自动绑定端口逻辑

不仅需要监听本地端口,而且一直与客户端的连接进行交互。有两种类型的channel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.util.Date;

public class NettyServer {

private static final int PORT = 8000;

public static void main(String[] args) {
//表示监听端口,accept新连接的线程组
//参数中不需要设置成1,nio线程本身是懒启动
NioEventLoopGroup boosGroup = new NioEventLoopGroup();
//表示处理每一条连接的数据读写的线程组
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
//服务端启动的引导类,可以对应Bio中的serversocket
final ServerBootstrap serverBootstrap = new ServerBootstrap();

serverBootstrap
//给引导类配置两大线程组
.group(boosGroup, workerGroup)
//配置IO模型,指定为NIO
.channel(NioServerSocketChannel.class)
//给服务端的channel设置一些属性,表示系统临时存放已完成三次握手队列的最大长度
.option(ChannelOption.SO_BACKLOG, 1024)
//表示开启TCP底层心跳机制
.childOption(ChannelOption.SO_KEEPALIVE, true)
//表示开启Nagle方法,需要减少发送次数,以及减少网络交互,就开启
.childOption(ChannelOption.TCP_NODELAY, true)
//给引导类创建一个ChannelInitializer,定义后序每条数据的连接读写
.childHandler(new ChannelInitializer() {
protected void initChannel(NioSocketChannel ch) {
ch.pipeline().addLast(new ServerHandler());
}
});

//原来的是serverfBootstrap.bind(8000),这个方法是一个异步的方法,返回的是一个ChannelFuture,
//可以给这个ChannelFuture添加一个监听器,在方法片段里添加判断端口是否绑定成功
bind(serverBootstrap, PORT);
}
//实现自动绑定端口逻辑
private static void bind(final ServerBootstrap serverBootstrap, final int port) {
//lambda表达式
serverBootstrap.bind(port).addListener(future -> {
if (future.isSuccess()) {
System.out.println(new Date() + ": 端口[" + port + "]绑定成功!");
} else {
System.err.println("端口[" + port + "]绑定失败!");
//不用lambda表达式的话,还要重新调用自身方法,并且将端口号+1
bind(serverBootstrap, port+1);
}
});
}
}
0%